#include "threadPool.h"
#include <shadow.h>
//char *path = "/home/li/project/cloud-storage-project/wp-v1/userfile";//用户不可见
//用户的名字为当前工作目录

//获取盐值
void extractSaltValue(const char *sppwdp, char *salt)//密文、盐值、
{
    size_t len = strlen(sppwdp);

    const char *p = sppwdp + len - 1;//char 地址+len-1指向最后一个字符
    while(p >= sppwdp)//sppwdp指向密文首地址，p指向最后一个字母
    {
        if(*p == '$')
        {
            break;
        }
        --p;
    }
    size_t needLen = p - sppwdp + 1;//p指向密文第三个$, sppwdp指向密文开头第一个$，

    strncpy(salt, sppwdp, needLen);
    salt[needLen] = '\0';
}


int verifyUser(const char *username, const char *password)
{
    //获取密文
    struct spwd *sp = getspnam(username);//根据用户名提取密文sp->sp_pwdp
    if(sp == NULL)//表示失败
    {
        perror("getspnam");
        return -1;
    }
    //提取盐值
    char salt[1024] = {0};
    extractSaltValue(sp->sp_pwdp, salt);//密文、盐值

    //password + salt = sp->pwdp
    char *key = crypt(password, salt);//sp->sp_pwdp是密文，passsord是用户明文，返回值key是密文
    if(key == NULL)
    {
        perror("crypt");
        return -1;
    }
    printf("%s\n",key);
    key[strcspn(key, "\n")] = '\0';
    sp->sp_pwdp[strcspn(sp->sp_pwdp, "\n")] = '\0';
    printf("%s\n",sp->sp_pwdp);

    //验证密文
    if(strcmp(key, sp->sp_pwdp) == 0)
    {
        return 0;//验证通过返回0
    }
    else
    {
        return -1;//失败返回-1
    }
}



void * threadFunc(void * arg)
{
    printf("worker准备就绪\n");
    threadPool_t * pthreadPool=(threadPool_t *)arg;
    while(1)
    {
        pthread_mutex_lock(&pthreadPool->mutex);
        while(pthreadPool->exitFlag==0&&pthreadPool->taskQueue.queueSize<=0)
        {
            pthread_cond_wait(&pthreadPool->cond,&pthreadPool->mutex);            
        }
        if(pthreadPool->exitFlag==1)
        {
            printf("i am worker becaust signal of  i goint to eixt\n");
            pthread_mutex_unlock(&pthreadPool->mutex);
            exit(0);
        }

        int netfd=pthreadPool->taskQueue.pFront->netfd;
        printf("i am worker i get netfd%d\n",netfd);
        deQueue(&pthreadPool->taskQueue);
        pthread_mutex_unlock(&pthreadPool->mutex);

        char userName[1024] = {0};
        char password[1024] = {0};
        char  userDirs[100][10] = {
            "user1",
            "user2",
            "user3",
            "user4",
            "user5",
        };
        while(1){
            int userCount = 5;
            printf("对方输入用户名\n");
            recv(netfd, userName, sizeof(userName), MSG_NOSIGNAL);//接收用户名
            printf("用户名接受成功！%s\n",userName);
            printf("对方输入密码\n");
            recv(netfd, password, sizeof(password), MSG_NOSIGNAL);//接收密码
            printf("密码接受成功！%s\n",password);
            int found = -1;
            userName[strcspn(userName, "\n")] = '\0';
            password[strcspn(password, "\n")] = '\0';
            for(int i = 0; i < userCount; ++i)
            {
                if(strcmp(userDirs[i],userName) == 0)
                {
                    found = i;
                    break;
                }
            }
            if(found==-1){
                                //send(netfd,"-1",3, MSG_NOSIGNAL);
                                //
                                //            
            }
            if(found >= 0)
            {
                //进行密码验证
                int ret = verifyUser(userDirs[found],password);
                if(ret == 0)//验证成功
                {
                    send(netfd, "0", 2, MSG_NOSIGNAL);
                    break;
                }
                else send(netfd, "-1", 3, MSG_NOSIGNAL);
                //到这里，就可以进行文件操作了
            }
        }//while结束
        /////////////////////////////////////////////文件目录操作
        stringStack_t stack;
        stringStackInit(&stack);
        int empty_num=0;
        while(1)
        {
            train_t train;
            memset(&train, 0, sizeof(train));

            char temp[1024] = {0};

            int ret = recv(netfd, &train, sizeof(train), 0);
            if(empty_num>10)break;
            if(ret <= 0)
            {
                empty_num++;
                perror("recv failed");
                continue;
            }
            printf("train.flag = %d, train.length = %d, train.data = %s\n", train.flag,train.length,train.data);
            char server_work_path[200]={0};
            strcat(server_work_path,ROOT_PATH);
            strcat(server_work_path,"/");
            strcat(server_work_path,userName);
            char client_work_path[100]={0};
            func_pwd(client_work_path,&stack);
            strcat(server_work_path,client_work_path);
            char true_file_path[300]={0};
            strcat(true_file_path,server_work_path);//gets puts mkdir rmdir remove 用到
            if(strlen(train.data)>0)strcat(true_file_path,"/");
            strcat(true_file_path,train.data);
            printf("true_file_path :%s\n",true_file_path);
            //cd
            if(train.flag ==1)
            {
                ssize_t ret =  func_cd(train.data,&stack,userName);
                if(ret == 0) send(netfd, "0", 1,  MSG_NOSIGNAL);
                else send(netfd, "-1",2, MSG_NOSIGNAL);
            }
            //ls
            else if(train.flag == 2)
            {
                ssize_t ret = func_ls(temp, &stack,userName);
                if(ret == 0) send(netfd, temp, strlen(temp), MSG_NOSIGNAL);
                else send(netfd, "-1", 2, MSG_NOSIGNAL);
            }
            //puts  客户端puts上传
            else if(train.flag == 3)
            {
                ssize_t ret = func_gets(netfd,true_file_path, &stack);
                if(ret == 0) send(netfd, "0", 1, MSG_NOSIGNAL);
                else send(netfd, "-1", 2, MSG_NOSIGNAL);
            }
            //gets  客户端gets下载
            else if(train.flag == 4)
            {
                printf("用户正在下载\n");
                ssize_t ret = func_puts(netfd,true_file_path,train.data, &stack);
                if(ret == 0) send(netfd, "0", 1, MSG_NOSIGNAL);
                else send(netfd, "-1", 2, MSG_NOSIGNAL);
            }
            //remove 删除服务器的文件
            else if(train.flag == 5)
            {
                ssize_t ret = func_remove(true_file_path, &stack);
                if(ret == 0) send(netfd, "0", 1, MSG_NOSIGNAL);
                else send(netfd, "-1", 2, MSG_NOSIGNAL);
            }
            //pwd
            else if(train.flag == 6)
            {
                ssize_t ret = func_pwd(temp, &stack);
                if(ret == 0)send(netfd, temp, strlen(temp), MSG_NOSIGNAL);
                else send(netfd, "-1", 2, MSG_NOSIGNAL);
            }
            //mkdir
            else if(train.flag == 7)
            {
                ssize_t ret = func_mkdir(true_file_path,&stack);
                if(ret == 0) send(netfd, "0", 1,  MSG_NOSIGNAL);
                else send(netfd, "-1", 2, MSG_NOSIGNAL);
            }
            //rmdir
            else if(train.flag == 8)
            {
                ssize_t ret =  func_rmdir(true_file_path,&stack);
                if(ret == 0) send(netfd, "0", 1, MSG_NOSIGNAL);
                else send(netfd, "-1", 2, MSG_NOSIGNAL);
            }  

        }
        close(netfd);
    }
    return NULL;

}

//创建子线程
int makeworker(threadPool_t * pthreadPool)
{
    for(int i=0;i<pthreadPool->tidArr.workNum;i++)
    {
        pthread_create(&pthreadPool->tidArr.arr[i],NULL,threadFunc,pthreadPool);
    }
    return 0;
}

